<template>  
	<template v-for='(v,i) in data' :key='i'>
		<template v-if='fn.hasObject(v)'>
			<div class='w' v-if='v.br'></div>
			<FormItem
				v-if 		= '!v.hide'
				:label 		= 'v.label'
				:name 		= 'v.name'
				:width 		= 'setWidth(v)'
				:mb 		= 'v.mb ?? mb'
				:ml 		= 'v.ml'
				:rules 		= "setRules(v)"
				:class 		= 'setClass(v)'
				:autoLink 	= "v.type !== 'tree'"
			>
				<Select 
					v-if 			= "v.type === 'select'"  
					v-model:value 	= 'form[v.name]'
					:name 			= 'v.name'
					:label 			= 'v.label'
					:form 			= 'config.form'
					:data 			= 'v.data'
					:disabled 		= 'setDisabled(v)'
					:readOnly 		= "setName(v, 'readOnly')"
					:api 			= 'v.api'
					:idStr 			= 'v.idStr'
					:nameStr 		= 'v.nameStr'
					:param 			= 'v.param'
					:paging 		= 'v.paging'
					:p 				= "setHolder(v,1)"
					:sname 			= 'v.sname'
					:formRef 		= 'submitRef'
					:cache 			= "setName(v, 'cache')"
					:multiple 		= 'Boolean(v.mul)'
					:count 			= 'v.count'
					@change 		= 'setChange($event,v)'
				/>
				<Transfer
					v-else-if 		= "v.type === 'transfer'"  
					v-model:value 	= 'form[v.name]' 
					:data 			= 'v.data' 
					:disabled 		= 'setDisabled(v)'
					:readOnly 		= "setName(v, 'readOnly')"
					:api 			= 'v.api'
					:idStr 			= 'v.idStr'
					:nameStr 		= 'v.nameStr'
					:param 			= 'v.param'
					:paging 		= 'v.paging'
					:p 				= "setHolder(v,1)"
					:setName 		= 'v.setNames'
					:cache 			= "setName(v, 'cache')"
					@change 		= 'setChange($event,v)'
					:title 			= 'v.title || config.title || config.editTitle'
					:height 		= 'v.height'
				/>
				<TreeSelect
					v-else-if 		= "v.type === 'tree-select'"  
					v-model:value 	= 'form[v.name]' 
					:data 			= 'v.data'
					:name 			= 'v.name'
					:label 			= 'v.label'
					:form 			= 'config.form'
					:disabled 		= 'setDisabled(v)'
					:api 			= 'v.api'
					:idStr 			= 'v.idStr'
					:nameStr 		= 'v.nameStr'
					:param 			= 'v.param'
					:p 				= "setHolder(v,1)"
					:cache 			= "setName(v, 'cache')"
					:multiple 		= 'false'
					:expand 		= 'v.expand'
					@change 		= 'setChange($event,v)'
				/>
				<Tree
					v-else-if 		= "v.type === 'tree'"  
					v-model:value 	= 'form[v.name]' 
					:data 			= 'v.data'
					:disabled 		= 'setDisabled(v)'
					:api 			= 'v.api'
					:idStr 			= 'v.idStr'
					:nameStr 		= 'v.nameStr'
					:param 			= 'v.param'
					:p 				= "setHolder(v)"
					:cache 			= "setName(v, 'cache')"
					:multiple 		= 'v.mul'
					:controls 		= 'v.controls'
					:expand 		= 'v.expand'
					:expandedKeys 	= 'v.expandedKeys'
					:block 			= 'v.block'
					@change 		= 'setChange($event,v)'
				/>
				<Radio
					v-else-if 		= "v.type === 'radio'"  
					v-model:value 	= 'form[v.name]' 
					:name 			= 'v.name'
					:label 			= 'v.label'
					:form 			= 'config.form'
					:data 			= 'v.data' 
					:disabled 		= 'setDisabled(v)'
					:readOnly 		= "setName(v, 'readOnly')"
					:mode 			= 'v.mode'
					:api 			= 'v.api'
					:idStr 			= 'v.idStr'
					:nameStr 		= 'v.nameStr'
					:param 			= 'v.param'
					:p 				= "setHolder(v,1)"
					:cache 			= "setName(v, 'cache')"
					@change 		= 'setChange($event,v)'
				/>
				<Switch
					v-else-if 		= "v.type === 'switch'"  
					v-model:value 	= 'form[v.name]'
					:name 			= 'v.name'
					:label 			= 'v.label'
					:form 			= 'config.form'
					:disabled 		= 'setDisabled(v)'
					:readOnly 		= "setName(v, 'readOnly')"
					@change 		= 'setChange($event,v)'
				/>
				<CheckboxGroup
					v-else-if 		= "v.type === 'checkbox-group'"  
					v-model:value 	= 'form[v.name]'
					:name 			= 'v.name'
					:label 			= 'v.label'
					:form 			= 'config.form'
					:data 			= 'v.data' 
					:disabled 		= 'setDisabled(v)'
					:readOnly 		= "setName(v, 'readOnly')"
					:mode 			= 'v.mode'
					:api 			= 'v.api'
					:idStr 			= 'v.idStr'
					:nameStr 		= 'v.nameStr'
					:param 			= 'v.param'
					:p 				= "setHolder(v,1)"
					:cache 			= "setName(v, 'cache')"
					:width 			= 'v.labelWidth'
					@change 		= 'setChange($event,v)'
				/>
				<DatePicker 
					v-else-if 		= "v.type === 'date' || v.type === 'date-range'" 
					v-model:value 	= 'form[v.name]'
					:name 			= 'v.name'
					:label 			= 'v.label'
					:form 			= 'config.form'
					:type 			= 'v.type'
					:disabled 		= 'setDisabled(v)'
					:readOnly 		= "setName(v, 'readOnly')"
					:p 				= "setHolder(v,1)"
					:format 		= 'v.format'
					:start 			= 'v.start'
					:end 			= 'v.end'
					:after 			= 'v.after'
					:before 		= 'v.before'
					:today 			= 'v.today'
					@change 		= 'setChange($event,v)'
				/>
				<Upload
					v-else-if 		= "v.type === 'upload'" 
					v-model:value 	= 'form[v.name]' 
					:name 			= 'v.name'
					:label 			= 'v.label'
					:form 			= 'config.form'
					:fileName 		= 'v.fileName'
					:list 			= 'v.list'
					:param 			= 'v.param'
					:way 			= 'v.way'
					:disabled 		= 'setDisabled(v)'
					:multiple 		= 'v.mul'
					:mode 			= 'v.mode'
					:api 			= 'v.api'
					:my 			= 'v.my'
					:fileType 		= 'v.fileType'
					@change 		= 'setChange($event,v)'
				/>
				<div v-else-if="v.type==='div'"></div>
				<div v-else-if="v.type==='slot'">
					<slot :name='v.name' :n='v.name' :f='form' :data='v.data' :disabled='setDisabled(v)' :readOnly="setName(v, 'readOnly')"></slot>
				</div>
				<div v-else-if="v.type==='render'">
					<!-- {{ v.customRender({ form, name, disabled, readOnly }) }} -->
					<RenderDom :render='v.customRender' :form='form' :data='{
						formRef,
						name 		: v.name, 
						p 			: setHolder(v),
						data  		: v.data, 
						value 		: form[v.name], 
						disabled 	: v.disabled, 
						readOnly 	: v.readOnly,
						label  		: v.label,
						size 		: config.size,
						api 		: v.api
					}' />
				</div>
				<SelectContent
					v-else-if 		= "v.type === 'select-content'"  
					v-model:value 	= 'form[v.name]' 
					:disabled 		= 'setDisabled(v)'
					:readOnly 		= "setName(v, 'readOnly')"
					:p 				= "setHolder(v,1)"
					:size 			= 'config.size'
					:rows 			= 'v.rows'
					:mode 			= 'v.mode'
					:btnText 		= 'v.btnText'
					@click 			= 'value => v.click({ formRef:submitRef, form, value  })'
					@change 		= 'setChange($event,v)'
				/> 
				<Table
					v-else-if 		= "v.type === 'table'"  
					v-model:value 	= 'form[v.name]'
					:config 		= 'v.table ?? {}'
					:data 			= 'v.data'
					:isSubmitForm 	= 'true'
					@change 		= 'setChange($event,v)'
				/>
				<Input
					v-else 
					v-model:value 	= 'form[v.name]'
					:name 			= 'v.name'
					:label 			= 'v.label'
					:size 			= 'config.size'
					:form 			= 'config.form'
					:disabled 		= 'setDisabled(v)'
					:readOnly 		= "setName(v, 'readOnly')"
					:type 			= 'v.type'
					:p 				= 'setHolder(v)'
					:money 			= 'v.money'
					:rows 			= 'v.rows'
					:step 			= 'v.step'
					:min 			= 'v.min'
					:max 			= 'v.max'
					@change 		= 'setChange($event,v)'
				/>
			</FormItem>	
		</template>
	</template>
</template>

<script setup>
	import { watch, ref } from 'vue'
	import { DownCircleOutlined } from '@ant-design/icons-vue'
	/* --------------------------- Component --------------------------- */
	const FormItem 		= $.lazy(()=>import('@antd/form/layout/form-item.vue'))
	const Input 		= $.lazy(()=>import('@antd/form/input.vue'))
	const Select 		= $.lazy(()=>import('@antd/form/select.vue'))
	const Radio 		= $.lazy(()=>import('@antd/form/radio.vue'))
	const CheckboxGroup = $.lazy(()=>import('@antd/form/checkbox-group.vue'))
	const Switch 		= $.lazy(()=>import('@antd/form/switch.vue'))
	const DatePicker 	= $.lazy(()=>import('@antd/form/date-picker.vue'))
	const Upload 		= $.lazy(()=>import('@antd/form/upload.vue'))
	const Transfer 		= $.lazy(()=>import('@antd/form/transfer.vue'))
	const TreeSelect 	= $.lazy(()=>import('@antd/tree/tree-select.vue'))
	const Tree 			= $.lazy(()=>import('@antd/tree/tree-checked.vue'))
	const Table 		= $.lazy(()=>import('@antd/table.vue'))
	// const Tags 		= $.lazy(()=>import('#cpt/form-element/tags.vue'))
	const SelectContent = $.lazy(()=>import('#cpt/form-element/select-content.vue'))
	/* --------------------------- 自定义接收 render --------------------------- */
	const RenderDom = {
		props:['render', 'data', 'form'],
		setup(props, ctx){
			let { render, data, form } = props
			
			const modelValue = ref( data?.value )
			const modelData = ref( data?.data )
			
			watch( ()=>props.data.value, value => modelValue.value = value )
			watch( ()=>props.data.data, value => modelData.value = value )
			
			return () => render( form, {...data, data:modelData.value, value:modelValue.value } )
		}
	}
	/* --------------------------- props --------------------------- */
	const props = defineProps({
		data	: { type: Array, default: [] },
		form	: Object,
		loading	: Boolean,
		edit	: Boolean,
		width	: Number,
		config	: Object,
		ajax 	: Object,
		mb 		: Number,
		formRef	: null,
		submitRef: null
	})
	const { config, formRef } = props
	const fn = $fn
	// 设置 name
	const setName = (v,name) => {
		if($fn.isValid(v[name])){
			return v[name]
		}else if($fn.isValid(config[name])){
			return config[name]
		}else {
			return props[name]
		}
	}
	
	// 设置输入提示
	const setHolder = ({ p, label='', type }, flag) => {
		const prefix = flag ? '请选择' : '请输入'
		let holder = prefix + label
		if( flag ){
			holder = label.includes(prefix) ? label : holder
		}else{
			if( type === 'img-code' || type === 'phone-code'){
				holder = '请输入验证码'
			}
		}
		return p ? p : holder
	}
	
	const setMsg = ({ type, label, mode, msg }) => {
		if(msg){ return msg }
		if(type === 'tags'){
			return '请' +  label
		}else if( type ==='upload'){
			return '请上传' + label 
		}else{
			return ['date','date-range','time','select', 'tree-select'].includes(type) ? '请选择' + label : '请输入' + label 
		}
	}
	// 设置宽度
	const setWidth = value => {
		if(value.half){
			return '50%'
		}else if(value.auto){
			return 'auto'
		}else if(value.width){
			return value.width
		}else{
			return config.width || '100%'
		}
	}
	// 禁用
	const setDisabled = v => {
		let bool = props.loading || props.ajax.loading || $fn.getResult(config.disabled) || $fn.getResult(v.disabled) || (config.edit && !props.edit)
		if(v.type === 'upload'){
			const readOnly = setName(v,'readOnly')
			bool =  readOnly ? readOnly :bool
		}
		return Boolean(bool)
	}
	// 设置 className
	const setClass = ({ type, fixed }) => {
		const text = ['phone-code', 'img-code', 'password'].includes(type) ? ' jzer-item-text ' : ' '
		return  'jzer-item-' + (type??'text') + text
	}
	// 改变时执行
	const setChange = (value, rows) => {
		if($fn.isObject(value)){ 
			rows?.change?.({...value, formRef })
		}else{
			rows?.change?.({value, formRef })
		}
	}
	// 表单验证
	const setRules = v => {
		const required = { required: true, message: setMsg(v), trigger: ['change','blur'], type: setType(v) }
		const rules = $fn.getResult(v.rules)
		const r = $fn.getResult(v.r)
		const isRequried = (  r && !config.disabled)
		if(rules){
			let s
			if($fn.hasObject(rules)){
				s =  isRequried ?  [ required, rules] : [ rules ]
			}else if($fn.hasArray(rules)){
				s = isRequried ?  [ required, ...rules] : rules
			}
			return s
		}else{
			return  isRequried ? required : null
		}
	}
	
	const setType = ({type, mul, t, mode}) => {
		if( t ) return t
		
		if(['tree-select','tree', 'transfer', 'checkbox-group', 'tags'].includes(type)){
			return mul ? 'array' : 'number'
		}else if( ['number'].includes(type) ){
			return 'number'
		}else{
			return 'string'
		}
	}
</script>